<template>
   <div class="editTableRowDemoWrap">
      <a-table
         :columns="columns"
         :dataSource="dataSource"
         :loading="isLoading"
         :pagination="false"
         :expandRowByClick="true"
         bordered
      >
         <template
            v-for="col in [
               'name',
               'idNum',
               'mobile',
               'accountRule',
               'cardAmount',
               'email'
            ]"
            :slot="col"
            slot-scope="text, record"
         >
            <div :key="col" style="position: relative">
               <!--姓名-->
               <div v-if="col === 'name'" style="position: relative">
                  <template v-if="record.editable">
                     <a-input
                        :value="text"
                        @change="e => handleChange(e.target.value, record.key, col)"
                     />
                     <div
                        class="errInfo"
                        v-if="!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(text.toString().trim())"
                     >
                        姓名仅支持中文汉字
                     </div>
                  </template>
                  <template v-else>
                     {{ text }}
                     <div class="errShowOnce" v-if="record.errInfo">{{record.errInfo}}</div>
                  </template>
               </div>

               <!--身份证号-->
               <div v-if="col === 'idNum'">
                  <template v-if="record.editable">
                     <a-input
                        :value="text"
                        @change="e => handleChange(e.target.value, record.key, col)"
                     />
                     <div
                        class="errInfo"
                        v-if="text.toString().trim().length !== 18"
                     >
                        请输入18位的身份证号码
                     </div>
                  </template>
                  <template v-else>{{ text }}</template>
               </div>

               <!--手机号-->
               <div v-if="col === 'mobile'">
                  <template v-if="record.editable">
                     <a-input
                        :value="text"
                        @change="e => handleChange(e.target.value, record.key, col)"
                     >
                     </a-input>
                     <div
                        class="errInfo"
                        v-if="text.toString().trim().length !== 11"
                     >
                        请输入11位正确的手机号
                     </div>
                  </template>
                  <template v-else>{{ text }}</template>
               </div>

               <!--记账规则-->
               <div v-if="col === 'accountRule'">
                  <template v-if="record.editable">
                     <a-select
                        style="width: 100%"
                        :options="accountRules"
                        :defaultValue="text"
                        @change="value => handleChange(value, record.key, col)"
                     />
                  </template>
                  <template v-else>{{ text | accountRuleFormat }}</template>
               </div>

               <!--卡片额度-->
               <div v-if="col === 'cardAmount'">
                  <template v-if="record.editable">
                     <a-input
                        :value="text"
                        @change="e => handleChange(e.target.value, record.key, col)"
                     >
                        <custom-icon slot="prefix" type="icon-rmb" />
                     </a-input>
                     <div class="errInfo" v-if="Number(text) > entAmount">
                        不能超过企业额度{{ entAmount }}
                     </div>
                     <div class="errInfo" v-if="!text">
                        请输入卡片额度
                     </div>
                  </template>
                  <template v-else>
                     <custom-icon type="icon-rmb" />
                     {{ text | formatMoney }}
                  </template>
               </div>

               <!--企业邮箱(校验规则只是校验是否有@和.)-->
               <div v-if="col === 'email'">
                  <template v-if="record.editable">
                     <a-input
                        :value="text"
                        @change="e => handleChange(e.target.value, record.key, col)"
                     >
                     </a-input>
                     <div
                        class="errInfo"
                        v-if="!(/\@.*\./.test(text.toString().trim()))"
                     >
                        请输入正确的企业邮箱
                     </div>
                  </template>
                  <template v-else>{{ text }}</template>
               </div>
            </div>
         </template>

         <!--操作-->
         <template slot="operation" slot-scope="text, record">
            <div class="editable-row-operations">
               <div v-if="record.editable" class="operationItem">
                  <a @click="save(record.key)">保存</a>
                  <!--当record中存在addFlag字段的时候，取消操作不显示-->
                  <a-popconfirm
                     okText="是"
                     cancelText="否"
                     title="确认是否取消?"
                     @confirm="cancel(record.key)"
                     v-if="!record.addFlag"
                  >
                     <a>取消</a>
                  </a-popconfirm>
                  <a-popconfirm
                     okText="是"
                     cancelText="否"
                     title="确认是否删除?"
                     @confirm="onDelete(record.key)"
                  >
                     <template slot="icon">
                        <a-icon style="color: #ff0000" type="warning" />
                     </template>
                     <a>删除</a>
                  </a-popconfirm>
               </div>
               <span v-else>
                  <a @click="edit(record.key)">编辑</a>
               </span>
            </div>
         </template>
      </a-table>

      <a-button
         icon="plus"
         type="dashed"
         style="width: 100%; margin-top: 20px;"
         @click="handleAdd"
      >
         添加
      </a-button>

      <a-button type="primary" class="doInvite" @click="doInvite">
         确认无误，去邀请
      </a-button>
      <a-modal
         title="温馨提示"
         cancelText="取消"
         okText="确认"
         :centered="true"
         :visible="visible"
         @ok="doInviteSubmit"
         :confirmLoading="confirmLoading"
         @cancel="cancelSubmit"
      >
         <p style="font-size: 20px">请再次确认</p>
      </a-modal>
   </div>
</template>

<script>
import { formatMoney } from '@/utils/util'
import customIcon from '@/utils/customIcon'

const columns = [
   {
      title: '姓名',
      dataIndex: 'name',
      width: '15%',
      scopedSlots: { customRender: 'name' }
   },
   {
      title: '身份证号',
      dataIndex: 'idNum',
      scopedSlots: { customRender: 'idNum' }
   },
   {
      title: '手机号',
      dataIndex: 'mobile',
      scopedSlots: { customRender: 'mobile' }
   },
   {
      title: '记账规则',
      dataIndex: 'accountRule',
      scopedSlots: { customRender: 'accountRule' }
   },
   {
      title: '卡片额度',
      dataIndex: 'cardAmount',
      scopedSlots: { customRender: 'cardAmount' }
   },
   {
      title: '企业邮箱',
      dataIndex: 'email',
      scopedSlots: { customRender: 'email' }
   },
   {
      title: '操作',
      dataIndex: 'operation',
      scopedSlots: { customRender: 'operation' }
   }
]
const dataSource = []
const accountRules = [
   { label: '默认因公', value: 'business' },
   { label: '默认因私', value: 'private' }
]

for (let i = 0; i < 3; i++) {
   dataSource.push({
      key: i.toString(),
      name: `Edrward ${i}`,
      idNum: 340826888804174416,
      mobile: 13750896737,
      accountRule: 'business',
      cardAmount: 2000,
      email: '990705166@qq.com',
      errInfo: '这是后台返回的错误信息'
   })
}

export default {
   name: 'editTableRowDemo',
   data () {
      // 拷贝原始数据副本，后续保存数据修改与取消数据修改时候用到
      this.cachedDataSource = dataSource.map(item => ({ ...item }))
      return {
         entAmount: 5000, // mock企业额度
         columns,
         dataSource,
         isLoading: false,
         visible: false,
         accountRules
      }
   },
   components: {
      customIcon
   },
   filters: {
      formatMoney,
      accountRuleFormat (val) {
         if (val === 'business') {
            return '默认因公'
         } else if (val === 'private') {
            return '默认因私'
         }
      }
   },
   methods: {
      // 触发编辑
      edit (key) {
         const newData = [...this.dataSource]
         const target = newData.filter(item => key === item.key)[0]
         if (target) {
            target.editable = true
            // 后台返回的错误信息只展示一次,一旦点了编辑就不再显示
            if (target.errInfo) {
               target.errInfo = void (0)
            }
            this.dataSource = newData
         }
      },
      // 编辑状态下检查字段错误信息
      openNotification (target) {
         if (
            !(/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(target.name.toString().trim())) ||
            target.idNum.toString().trim().length !== 18 ||
            target.mobile.toString().trim().length !== 11 ||
            Number(target.cardAmount) > this.entAmount ||
            !(/@.*\./.test(target.email.toString().trim()))
         ) {
            this.$notification.open({
               message: '操作失败',
               description: '存在不符合填写规范的内容，请修改后再操作',
               duration: 2
            })
            return true
         }
         return false
      },
      // 编辑保存
      save (key) {
         const newData = [...this.dataSource]
         const target = newData.filter(item => key === item.key)[0]

         // 这里判断下是否有报错信息（前端校验的验证）,如果有的话不允许保存，提示有错误
         if (!this.openNotification(target) && target) {
            // 保存成功时候将通过手动添加的行标志删除
            if (target.addFlag) {
               delete target.addFlag
            }
            delete target.editable
            this.dataSource = newData
            // 更新原始数据副本
            this.cachedDataSource = newData.map(item => ({ ...item }))
         }
      },
      // 编辑取消
      cancel (key) {
         const newData = [...this.dataSource]
         const target = newData.filter(item => key === item.key)[0]

         // 这里判断下是否有报错信息（前端校验的验证）,如果有的话不允许取消，提示有错误
         if (!this.openNotification(target) && target) {
            // 将旧的数值合并到target
            Object.assign(
               target,
               this.cachedDataSource.filter(item => key === item.key)[0]
            )
            delete target.editable
            this.dataSource = newData
         }
      },
      // 编辑删除
      onDelete (key) {
         const dataSource = [...this.dataSource]
         this.dataSource = dataSource.filter(item => item.key !== key)
         this.cachedDataSource = this.dataSource.map(item => ({ ...item }))
      },
      // 单元格编辑监听(注意处理记账规则时参数)
      handleChange (value, key, column) {
         const newData = [...this.dataSource]
         const target = newData.filter(item => key === item.key)[0]
         if (target) {
            target[column] = value
            this.dataSource = newData
         }
      },
      // 增加一行
      handleAdd () {
         let { dataSource } = this
         let newData = {
            key: dataSource.length.toString(),
            name: '',
            idNum: '',
            mobile: '',
            accountRule: 'business',
            cardAmount: 0,
            email: '',
            editable: true,
            addFlag: true
         }
         this.dataSource = [...dataSource, newData]
      },
      // 提交前的二次确认
      doInvite () {
         this.visible = true
      },
      cancelSubmit () {
         this.visible = false
      },
      // 确认无误 邀请
      doInviteSubmit () {
         this.visible = false
         this.isLoading = true
         // 模拟后台请求返回
         setTimeout(() => {
            this.isLoading = false
         }, 3000)
      }
   }
}
</script>

<style lang="less" scoped>
.editTableRowDemoWrap {
   padding-bottom: 30px;
}

.editable-row-operations {
   .operationItem {
      display: flex;
      flex-direction: column;
      margin-bottom: 3px;

      a {
         white-space: nowrap;
      }
   }
}

.editable-add-btn {
   margin-bottom: 8px
}

.doInvite {
   margin-top: 30px
}

.errInfo {
   font-size: 12px;
   color: #f63939;
   position: absolute;
}

.errShowOnce {
   position: absolute;
   font-size: 12px;
   color: #f63939;
}
</style>
<style lang="less">
.ant-notification-notice-message {
   color: #f63939
}
</style>
